﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using LuckyLoot.ServiceFacade.Contracts;
using LuckyLoot.ServiceFacade.Implementation;
using LuckyLoot.Presentation.BasePage;
using LuckyLoot.Common;
using LuckyLoot.Common.Validation;
using LuckyLoot.Domain.Aggregate;

namespace LuckyLoot.Presentation
{
    public partial class TattooApointmentPage : LuckyLootPage
    {

        private const string QueryStringTattooID = "TattooID";
        private IApointmentService _apointmentService;

        public IApointmentService ApointmentService
        {
            get
            {
                if (_apointmentService == null)
                    _apointmentService = new ApointmentService();

                return _apointmentService;
            }
        }

        public int TattooApointmentID
        {
            set
            {
                this.ViewState[QueryStringTattooID] = value;
                this.tattooID.Value = value.ToString();
            }
            get
            {
                int viewStateTypedTattooApointmentID;

                if (this.ViewState[QueryStringTattooID] != null)
                {
                    if (Int32.TryParse(this.ViewState[QueryStringTattooID].ToString(), out viewStateTypedTattooApointmentID))
                        return viewStateTypedTattooApointmentID;
                }

                return 0;
            }
        }

        public bool HasSelectedRecord 
        {
            get
            {
                return TattooApointmentID > 0;
            }
        }

        protected void Page_Load(object sender, EventArgs e)
        {
            try
            {
                this.MasterPage.HideMessages();

                this.BindArtists();
                this.BindCustomers();
                this.BindTattooSizes();
                this.BindTattooStyles();
                this.BindTattooColors();
                // TODO: COgitar a hipotese de criar uma tela para cadastrar os itens que serao usados nas tattoos
                if (!Page.IsPostBack)
                {
                    var apointmentIDString = HttpContext.Current.Request.QueryString[QueryStringTattooID];
                    this.SelectRecord(apointmentIDString);
                }

                this.SaveTattoo.Click += new EventHandler(SaveTattooClick);
                this.SaveSession.Click += new EventHandler(SaveSessionClick);
                this.SavePhotos.Click += new EventHandler(SavePhotosClick);
                this.NewTattoo.Click += new EventHandler(NewTattooClick);
                
                this.tattoosGrid.SelectedIndexChanged += new EventHandler(GridSelectedIndexChanged);

                this.BindGrid();
                this.BindImagesGrid();
                this.SetCommandsVisibility();
            }
            catch (Exception ex)
            {
                MasterPage.ShowErrorMessage(ex.Message);
            }
        }

        protected void SavePhotosClick(object sender, EventArgs e)
        {
            try
            {
                ValidState.Requires<InvalidOperationException>(this.HasSelectedRecord);

                byte[] photos = this.tattooPhotos.FileBytes;
                this.ApointmentService.UploadPicture(this.TattooApointmentID, photos);
            }
            catch (Exception ex)
            {
                MasterPage.ShowErrorMessage(ex.Message);
            }
        }

        public void NewTattooClick(object sender, EventArgs e)
        {
            this.ClearRecordSelection();
        }

        protected void SaveSessionClick(object sender, EventArgs e)
        {
            try
            {
                ValidState.Requires<ArgumentException>(HasSelectedRecord);

                DateTime date;
                if (!DateTime.TryParse(sessionDate.Text, out date)) 
                    throw new ArgumentException("Não foi possível converter em uma Data o valor informado no campo Data da próxima sessão.");

                this.ApointmentService.ScheduleTattooSession(this.TattooApointmentID, date);
            }
            catch (Exception ex)
            {
                MasterPage.ShowErrorMessage(ex.Message);
            }
        }

        protected void GridSelectedIndexChanged(object sender, EventArgs e)
        {
            GridViewRow row = tattoosGrid.SelectedRow;

            string stringId = row.Cells[1].Text;
            int id;
            if (Int32.TryParse(stringId, out id))
            {
                this.SelectRecord(id);
                this.SetCommandsVisibility();
            }

        }

        

        public void SaveTattooClick(object sender, EventArgs e)
        {
            try
            {
                DateTime date;
                if (!DateTime.TryParse(tattooDate.Text, out date))
                    throw new ArgumentException("Não foi possível converter em uma Data o valor informado no campo Data.");

                int customer;
                if (!Int32.TryParse(tattooCustomer.SelectedValue, out customer))
                    throw new ArgumentException("Não foi possível converter em um número o valor informado no campo Cliente.");

                int artist;
                if (!Int32.TryParse(tattooArtist.SelectedValue, out artist))
                    throw new ArgumentException("Não foi possível converter em um número o valor informado no campo Artista.");

                int size;
                if (!Int32.TryParse(tattooSize.SelectedValue, out size))
                    throw new ArgumentException("Não foi possível converter em um número o valor informado no campo Tamanho.");

                int style;
                if (!Int32.TryParse(tattooStyle.SelectedValue, out style))
                    throw new ArgumentException("Não foi possível converter em um número o valor informado no campo Estilo.");

                int color;
                if (!Int32.TryParse(tattooColors.SelectedValue, out color))
                    throw new ArgumentException("Não foi possível converter em um número o valor informado no campo Cores.");

                TattooApointment tattoo;
                if (HasSelectedRecord)
                    tattoo = this.ApointmentService.UpdateTattooApointment(TattooApointmentID, tattooTitle.Text, tattooDescription.Text, customer, artist, date, (TattooSize)size, (TattooStyle)style, (TattooColors)color);
                else
                    tattoo = this.ApointmentService.ScheduleTattoo(tattooTitle.Text, tattooDescription.Text, customer, artist, date, (TattooSize)size, (TattooStyle)style, (TattooColors)color);

                this.SelectRecord(tattoo);
                this.SetCommandsVisibility();

                MasterPage.ShowSuccessMessage("Agendamento de tatuagem salvo com sucesso!");
                this.BindGrid();
                this.BindImagesGrid();
            }
            catch (Exception ex)
            {
                MasterPage.ShowErrorMessage(ex.Message);
            }
        }

        private void SetCommandsVisibility()
        {
            this.AddSession.Visible = this.HasSelectedRecord;
            this.NewTattoo.Visible = this.HasSelectedRecord;
            this.AddPhotos.Visible = this.HasSelectedRecord;
        }

        private void SelectRecord(string id)
        {
            try
            {
                if (!string.IsNullOrWhiteSpace(id))
                {
                    int intID;
                    if (Int32.TryParse(id, out intID))
                        SelectRecord(intID);
                }
            }
            catch (Exception ex)
            {
                MasterPage.ShowErrorMessage(ex.Message);
            }
        }

        private void SelectRecord(int id)
        {
            try
            {
                ValidState.Requires<ArgumentException>(id > 0);
                var tattoo = this.ApointmentService.GetTattooApointment(id);

                SelectRecord(tattoo);
            }
            catch (Exception ex)
            {
                MasterPage.ShowErrorMessage(ex.Message);
            }
        }

        private void SelectRecord(TattooApointment tattoo)
        {
            try
            {
                this.tattooTitle.Text = tattoo.Title;
                this.tattooDescription.Text = tattoo.Description;
                this.tattooCustomer.SelectedValue = tattoo.Customer.Id.ToString();
                this.tattooArtist.SelectedValue = tattoo.Artist.Id.ToString();
                this.tattooDate.Text = tattoo.Sessions.First().Date.ToString();
                this.tattooSize.SelectedValue = ((int)tattoo.Size).ToString();
                this.tattooStyle.SelectedValue = ((int)tattoo.Style).ToString();
                this.tattooColors.SelectedValue = ((int)tattoo.Colors).ToString();

                this.TattooApointmentID = tattoo.Id;
            }
            catch (Exception ex)
            {
                MasterPage.ShowErrorMessage(ex.Message);
            }
        }

        private void ClearRecordSelection()
        {
            this.TattooApointmentID = 0;
            this.ClearFields();
        }

        private void ClearFields()
        {
            this.tattooTitle.Text = string.Empty;
            this.tattooDescription.Text = string.Empty;
            this.tattooCustomer.SelectedIndex = 0;
            this.tattooArtist.SelectedIndex = 0;
            this.tattooDate.Text = string.Empty;
            this.tattooSize.SelectedIndex = 0;
            this.tattooStyle.SelectedIndex = 0;
            this.tattooColors.SelectedIndex = 0;

            this.sessionDate.Text = string.Empty;
        }


        #region Binding

        private void BindArtists()
        {
            var userService = new UserService();
            var artists = userService.GetArtists();
            this.tattooArtist.Items.Clear();
            foreach (var artist in artists)
            {
                this.tattooArtist.Items.Add(new ListItem(artist.Name, artist.Id.ToString()));
            }
        }

        private void BindCustomers()
        {
            var customerService = new CustomerManagementService();
            var customers = customerService.GetAllCustomers();
            this.tattooCustomer.Items.Clear();
            foreach (var customer in customers)
            {
                this.tattooCustomer.Items.Add(new ListItem(customer.Name, customer.Id.ToString()));
            }
        }

        private void BindTattooSizes()
        {
            Array values = Enum.GetValues(typeof(TattooSize));
            this.tattooSize.Items.Clear();
            foreach (TattooSize val in values)
            {
                this.tattooSize.Items.Add(new ListItem(val.GetDescription(), ((int)val).ToString()));
            }
        }
        
        private void BindTattooStyles()
        {
            Array values = Enum.GetValues(typeof(TattooStyle));
            this.tattooStyle.Items.Clear();
            foreach (TattooStyle val in values)
            {
                this.tattooStyle.Items.Add(new ListItem(val.GetDescription(), ((int)val).ToString()));
            }
        }

        private void BindTattooColors()
        {
            Array values = Enum.GetValues(typeof(TattooColors));
            this.tattooColors.Items.Clear();
            foreach (TattooColors val in values)
            {
                this.tattooColors.Items.Add(new ListItem(val.GetDescription(), ((int)val).ToString()));
            }
        }

        private void BindGrid()
        {
            var tattoos = this.ApointmentService.GetAllTattooApointments();

            if (tattoos.Count() > 0)
            {
               // this.tattoosGrid.AutoGenerateSelectButton = true;

                this.tattoosGrid.DataSource = tattoos;
                this.tattoosGrid.DataBind();
                this.tattoosGrid.Visible = true;
                this.tattoosLabel.Visible = true;
            }

            
        }

        private void BindImagesGrid()
        {
            if (this.HasSelectedRecord)
            {
                var pictures = this.ApointmentService.GetApointmentPictures(this.TattooApointmentID);

                if (pictures.Count > 0)
                {
                    this.tattooPhotosGrid.DataSource = pictures;
                    this.tattooPhotosGrid.DataBind();

                    //this.tattooPhotosGrid.Visible = true;
                    this.tattooPhotosLabel.Visible = true;
                }
            }
        
        }

        #endregion
    }
}